/**
 * (c) time4tea technology ltd 2007 - Freely redistributable as long as source is acknowledged
 */
package net.time4tea.rsync.matcher;


import java.io.File;
import java.io.IOException;

import org.hamcrest.Description;
import org.hamcrest.Factory;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeDiagnosingMatcher;

public class FileMatchers {

	@Factory
	public static Matcher<File> isDirectory() {
		return new TypeSafeDiagnosingMatcher<File>() {
			File fileTested;


			@Override
			protected boolean matchesSafely(File item, Description mismatchDescription) {
				fileTested = item;
				return item.isDirectory();
			}


			public void describeTo(Description description) {
				description.appendText(" that ");
				description.appendValue(fileTested);
				description.appendText("is a directory");
			}
		};
	}


	@Factory
	public static Matcher<File> exists() {
		return new TypeSafeDiagnosingMatcher<File>() {
			File fileTested;


			@Override
			protected boolean matchesSafely(File item, Description mismatchDescription) {
				fileTested = item;
				return item.exists();
			}


			public void describeTo(Description description) {
				description.appendText(" that file ");
				description.appendValue(fileTested);
				description.appendText(" exists");
			}
		};
	}


	@Factory
	public static Matcher<File> isFile() {
		return new TypeSafeDiagnosingMatcher<File>() {
			File fileTested;


			@Override
			protected boolean matchesSafely(File item, Description mismatchDescription) {
				fileTested = item;
				return item.isFile();
			}


			public void describeTo(Description description) {
				description.appendText(" that ");
				description.appendValue(fileTested);
				description.appendText("is a file");
			}
		};
	}


	@Factory
	public static Matcher<File> readable() {
		return new TypeSafeDiagnosingMatcher<File>() {
			File fileTested;


			@Override
			protected boolean matchesSafely(File item, Description mismatchDescription) {
				fileTested = item;
				return item.canRead();
			}


			public void describeTo(Description description) {
				description.appendText(" that file ");
				description.appendValue(fileTested);
				description.appendText("is readable");
			}
		};
	}


	@Factory
	public static Matcher<File> writable() {
		return new TypeSafeDiagnosingMatcher<File>() {
			File fileTested;


			@Override
			protected boolean matchesSafely(File item, Description mismatchDescription) {
				fileTested = item;
				return item.canWrite();
			}


			public void describeTo(Description description) {
				description.appendText(" that file ");
				description.appendValue(fileTested);
				description.appendText("is writable");
			}
		};
	}


	@Factory
	public static Matcher<File> sized(final Matcher<Long> size) {
		return new TypeSafeDiagnosingMatcher<File>() {
			File fileTested;

			long length;


			@Override
			protected boolean matchesSafely(File item, Description mismatchDescription) {
				fileTested = item;
				length = item.length();
				return size.matches(length);
			}


			public void describeTo(Description description) {
				description.appendText(" that file ");
				description.appendValue(fileTested);
				description.appendText(" is sized ");
				description.appendDescriptionOf(size);
				description.appendText(", not " + length);
			}
		};
	}


	@Factory
	public static Matcher<File> named(final Matcher<String> name) {
		return new TypeSafeDiagnosingMatcher<File>() {
			File fileTested;


			@Override
			protected boolean matchesSafely(File item, Description mismatchDescription) {
				fileTested = item;
				return name.matches(item.getName());
			}


			public void describeTo(Description description) {
				description.appendText(" that file ");
				description.appendValue(fileTested);
				description.appendText(" is named");
				description.appendDescriptionOf(name);
				description.appendText(" not ");
				description.appendValue(fileTested.getName());
			}
		};
	}


	@Factory
	public static Matcher<File> withCanonicalPath(final Matcher<String> path) {
		return new TypeSafeDiagnosingMatcher<File>() {

			@Override
			protected boolean matchesSafely(File item, Description mismatchDescription) {
				try {
					return path.matches(item.getCanonicalPath());
				} catch (IOException e) {
					return false;
				}
			}


			public void describeTo(Description description) {
				description.appendText("with canonical path '");
				description.appendDescriptionOf(path);
				description.appendText("'");
			}
		};
	}


	@Factory
	public static Matcher<File> withAbsolutePath(final Matcher<String> path) {
		return new TypeSafeDiagnosingMatcher<File>() {
			@SuppressWarnings("unused")
			File fileTested;


			@Override
			protected boolean matchesSafely(File item, Description mismatchDescription) {
				fileTested = item;
				return path.matches(item.getAbsolutePath());
			}


			public void describeTo(Description description) {
				description.appendText("with absolute path '");
				description.appendDescriptionOf(path);
				description.appendText("'");
			}
		};
	}
}